<?php

// +----------------------------------------------------------------------
// | ADM Software [ 我宁可 为做过的事而后悔，也不想 因为没尝试而后悔。 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2014 扬州安蝶梦电子商务有限公司 All rights reserved.
// +----------------------------------------------------------------------
// | Author: 曹梦龙 <138888611@qq.com> <http://www.andiemeng.com>
// +----------------------------------------------------------------------

namespace Org\BMap;

//简易地理信息工具
class GeoUtils {

     
     
     //求最大值
     public  function getMax($value1,$value2){
         if($value1>$value2){
             return $value1;
         }else{
             return $value2;
         }
         
     }
     //求最小值
     public  function getMin($value1,$value2){
         
         if($value1<$value2){
             return $value1;
         }else{
             return $value2;
         }
         
     }
     
     //判断是否相同
     public  function IsEqual($value1,$value2){
         $precision = 2e-10; //浮点类型计算时候与0比较时候的容差
         if($value1-$value2 < $precision && $value2-$value1 < $precision){
             return TRUE;
         }else{
             return FALSE;
         }
     }


     /*
      * 判断点与线段的关系
      * @param {Point} point 点对象
      * @param {Point1} 线段开始point 点对象
      * @param {Point2} 线段结束point 点对象
      * @returns 相交返回1 不想交返回0 射线起点在线段上返回-1
      * @author: 曹梦龙
      */
     public  function isIntersectant($Point,$Point1,$Point2){
         
         
         $X=$Point->lng;
         $Y=$Point->lat;
         $X1=$Point1->lng;
         $Y1=$Point1->lat;
         $X2=$Point2->lng;
         $Y2=$Point2->lat;
         
         //计算线段的最小和最大值
         $MinX= $this->getMin($X1,$X2);
         $MaxX= $this->getMax($X1,$X2);
         $MinY= $this->getMin($Y1,$Y2);
         $MaxY= $this->getMax($Y1,$Y2);
     
         //射线与边无交点的简单判断
         if($Y<$MinY || $Y>$MaxY || $X< $MinX){return 0;}
         
         //判断是否是水平线线段，并且点是否在线段上，
         if($this->IsEqual($MinY, $MaxY)){ // 判断是否是水平线段
             if($X>=$MinX && $X<=$MaxX){ //判断点是否在水平线段中
                 return -1;
             }  else {
                  return 0;
             }
         }
          
         //获取交点的X坐标
         $X0=$X1+($Y-$Y1)*($X2-$X1)/($Y2-$Y1);
           
         //交点在射线起点 右侧（射线与线段不想交）
         if($X0>$X){return 0;}
         
         //交点与射线起点相同，点在线段上，返回-1；
         if($this->IsEqual($X0, $X)){return -1;}
        
         //如果射线穿过线段下端点则不计数
         if($this->IsEqual($Y, $MinY)){return 0;}
       
         return 1;
     }

     

     /**
     * 判断点是否多边形内
     * @param {Point} point 点对象
     * @param {PointArray} polygon 多边形对象
     * @returns  点在多边形内返回1,否则返回0,点在多边形线上返回2
     * @author: 曹梦龙
     */
    public  function isPointInPolygon($Point, $PointArray) {
        //找出多边形的地理坐标的矩形区域
        $bounds = new Bounds($PointArray);
        //首先判断点是否在多边形的外包矩形内，如果在，则进一步判断，否则返回false
        $result=  $bounds->isPointInRect($Point);
      
        if($result==FALSE){
            return 0;
            
        }
        
        //计算该点向左方向的水平射线与多边形各边的交点个数 
        $nCount=0;
        $nVPonits=count($PointArray);
      
        for($i=0;$i<$nVPonits-1;$i++){
            $nFlag=  $this->isIntersectant($Point, $PointArray[$i], $PointArray[$i+1]); 
            if($nFlag<0){return 2;}
            $nCount=$nCount+$nFlag;
           
        }
        
        //考虑多边形末顶点和首顶点相连的边
        $nFlag=  $this->isIntersectant($Point, $PointArray[$nVPonits-1], $PointArray[0]);
        if($nFlag<0){return 2;}
        $nCount=$nCount+$nFlag;
       
        return ($nCount & 1); //判断奇偶，用的是二进制判断低位是否为1，如果是偶返回0 ，奇数返回1
    }
    
    
      /**
     * 判断点在哪个区域内，返回区域ID
     * @param {lng} 经度坐标
     * @param {lat} 纬度坐标
     * @returns  点在多边形内返回区域ID,否则返回0
     * @author: 曹梦龙
     */
     public  function isPointInArea($lng, $lat) {
            //创建点
          $point =new Point((float)$lng,(float)$lat);
           //多边形数据读取
           $PointsDataList= $AreaList = D('Area')->where("status=1")->select();
          
           for($i=0;$i<count($PointsDataList);$i++){
               $str=$PointsDataList[$i]['points'];
               $pointdataarray= split(';',$str);
               $pointArray= array();
                for($b=0;$b<count($pointdataarray);$b++){
                    $pointdata= split(',',$pointdataarray[$b]);
                    $pointzhi =new Point($pointdata[0],$pointdata[1]);
                    $pointArray[]=$pointzhi;
                }
                
                $result=  $this->isPointInPolygon($point, $pointArray); 
                if($result>0){
                    return $PointsDataList[$i]['id'];
                }
           }
           return 0;
     }     
     
     public  function isPointInJuiceArea($lng, $lat) {
            //创建点
          $point =new Point((float)$lng,(float)$lat);
           //多边形数据读取
           $PointsDataList= $AreaList = D('juice_area')->where("status=1")->select();
          
           for($i=0;$i<count($PointsDataList);$i++){
               $str=$PointsDataList[$i]['points'];
               $pointdataarray= split(';',$str);
               $pointArray= array();
                for($b=0;$b<count($pointdataarray);$b++){
                    $pointdata= split(',',$pointdataarray[$b]);
                    $pointzhi =new Point($pointdata[0],$pointdata[1]);
                    $pointArray[]=$pointzhi;
                }
                
                $result=  $this->isPointInPolygon($point, $pointArray); 
                if($result>0){
                    return $PointsDataList[$i]['id'];
                }
           }
           return 0;
     }     

}
